refactor(commands): move commands-side rendering out of src/daemon and retire the doctor progress flag - #2349
Conversation
…their callers `formatDoctorCheckSummaryLine`, `formatDoctorCheckDetailLines`, and `formatCliStatusMarker` are shared by the daemon doctor handlers, the CLI replay-test reporter, and the doctor CLI output formatter. Owning them in `src/daemon/handlers/` forced `src/commands` to reach up into `src/daemon` through a dynamic import; `src/core` sits below every caller. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
The `serialize*` helpers render command results for the CLI and MCP surfaces, not for the daemon; only the two deployment target resolvers were shared with daemon handlers. The serializers move to `src/commands/output/` beside the formatters that call them, and the resolvers move to `src/core` below both owners, so `src/commands` and `src/mcp` no longer reach into `src/daemon` for them. The MCP edge becomes a static import; the `src/commands` edges stay function-scoped because `src/cli.ts` eagerly evaluates both output modules. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
…ng the doctor progress flag Streamed `command` progress was rendered to stderr by the daemon client, which recorded "doctor progress was rendered" in a process-global flag that `doctorCliOutput` then consumed to suppress its final summary. The rendering was commands-side, so it moves there: the CLI installs `createStderrCommandProgressSink` as the request's `RequestProgressSink` for every non-`test`, non-`--json` command, and hands its `CommandProgressState` to the output formatters with the result. The transport now only forwards events to the sink the caller installed. Behavior is unchanged in the three modes the tests pin: progress streamed to stderr suppresses doctor's check lines, no progress prints them, and a caller that installs its own sink (SDK, MCP) writes nothing to this process's stderr and is not suppressed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
Completion evidenceZero edges from
|
Size Report
Startup median (7 runs, lower is better):
|
The end-to-end doctor progress cases landed in `cli-network.test.ts`, which is already past the 1,000-line tripwire, so the test-file-size ratchet rejected the growth. They are doctor-output cases rather than network ones: they move to `cli-doctor-progress.test.ts`, and `cli-network.test.ts` returns to its merge-base size. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
|
Clean review at 29f3527. The shared helpers and serializers have clear owners, and the doctor progress state is local to each CLI run. Streamed output avoids duplicates; custom sinks still get the full result. The tests cover both streamed and unstreamed CLI output, and the old global flag is gone. Ready for human review. Remaining CI is still running, so this is not yet a merge-ready claim. |
|
Summary
Closes #2337.
src/commandsandsrc/mcpreached intosrc/daemonfor rendering they own — 11import()sites, 5 file edges. Each moves to its owner:daemon/result-serialization.ts→commands/output/result-serialization.ts; the two deployment target resolvers its daemon handlers needed →core/deploy-result-target.ts.daemon/handlers/doctor-output.tsandhandlers/status-markers.ts→src/core/, below the daemon handlers, the replay-test reporter and the doctor formatter.daemon/client/doctor-progress.ts(a process-global flag) is deleted, not deprecated. The CLI installscreateStderrCommandProgressSinkas the request'sRequestProgressSinkand hands itsCommandProgressStateto the output formatters; the daemon client only forwards events to the caller's sink.The MCP edge becomes static. The
src/commandsedges stay function-scoped: static would takesrc/cli.tsfrom 380 to 384 eager modules, which the no-growth budget rejects. No budget raised, no compatibility re-export, no gate or baseline edit needed.Validation
Tested at
e4bc1ea:pnpm install --frozen-lockfile && pnpm build,pnpm typecheck,pnpm lint,pnpm check:affected --run— all runnable checks passed (270 files / 2025 tests, plus daemon-wire-compat).Graph query over
pnpm depgraphoutput (non-type edges,src/commands|src/mcp → src/daemon): 5 at27a97ee, 0 at head — query, both outputs and the rename-only stat in the first comment.pnpm check:layering: OK, 0 R5 back-edges, R2 clean. Eager-closure budgets: 442 pass; all 225 entries unchanged,src/cli.ts380 → 380.Doctor CLI output is byte-identical in all three modes (progress streamed, none, custom sink); captures diffed empty. The new CLI-level test was verified failing without the fix.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Eddu5VC45qAXUkXNZJyruZ
Generated by Claude Code